package com.fingard.dsp.bank.directbank.ceb01;

import java.io.File;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;

import com.fingard.constant.Format;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptData;
import com.fingard.dsp.bank.dbobj.receipt.ReceiptDataHelper;
import com.fingard.dsp.bank.directConfig.ReceiptProConfig;
import com.fingard.dsp.bank.directbank.bankInterface.IReceiptPro;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.ReqQryReceipt;
import com.fingard.dsp.bank.reqrespobj.downloadreceipt.RetAtsReceipt;
import com.fingard.dsp.task.command.SyncReceipt;
import com.fingard.io.FileHelper;
import com.fingard.text.StringHelper;
import com.fingard.util.DateHelper;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

public class CEB01ReceiptPro extends CEB01Base implements IReceiptPro{

	@Override
	public RetAtsReceipt qryReceiptOneDay(ReceiptProConfig pConfig, ReqQryReceipt pReqReceipt, Date pOneDay)
			throws Exception {

		String strCurrency = getBankConfig().getMapValueByKey("elereceiptAccountInfo", pReqReceipt.actNum);
        if (StringHelper.isNullOrEmpty(strCurrency)){
            strCurrency = "1";
        }
        this.WriteBankLogLn("currency:"+strCurrency);
        
        int tmpAllNum = -1;//总条数
        int tmpReadedNum = 0;//已读取数
        int existNum = 0;//已存在
        int insertNum = 0;//新增
        //每页条数
        int queryNum = this.getBankConfig().getValueAsInt("queryNum", 50, "receipt");
        if(queryNum<=0){
        	queryNum = 50;
        }
        int tmpStartNO = 0;//请求页码
        String tmpRespCode = "";
        ReceiptDataHelper receiptHelper = null;//回单数据保存类，分区分表
        try{
        	receiptHelper = new ReceiptDataHelper(pReqReceipt.reqHeader.tenant, pOneDay);
        	String qryDay8 = Format.Date8Format.format(pOneDay);
        	do{//分页查询
                tmpStartNO++;
                XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
                //写入通用的头部节点
                CEB01Header bankHeader = new CEB01Header();
                bankHeader.TransCode = "b2e005023";
                bankHeader.batchID = getBatchID();
                bankHeader.JnlDateTime = new Date();
                writeCommonHeader_2(xmlWriter, bankHeader);
                xmlWriter.writeStartElement("TransContent");
                xmlWriter.writeStartElement("ReqData");
                xmlWriter.writeElementString("ClientPatchID", bankHeader.batchID);
                xmlWriter.writeElementString("OperationType", "0");
                xmlWriter.writeElementString("ActNo", pReqReceipt.actNum);
                xmlWriter.writeElementString("BillNumber", "");
                xmlWriter.writeElementString("BeginDate", qryDay8);
                xmlWriter.writeElementString("EndDate", qryDay8);
                xmlWriter.writeElementString("BeginAmount", "");
                xmlWriter.writeElementString("EndAmount", "");
                xmlWriter.writeElementString("BeginNum", String.valueOf(tmpStartNO));
                xmlWriter.writeElementString("QueryNum", String.valueOf(queryNum));
                xmlWriter.writeEndDocument();
                //查询回单信息
                String[] tmpStrRet = sendToBank_2(xmlWriter.toXmlString(), bankHeader.TransCode);
                if (tmpStartNO > 1) {
                    tmpStrRet = new String[]{"", ""};
                }
                XmlTextReader tmpBkReader;
                boolean doRead = false;
                int tmpPageRdNum = 0;
                if (tmpStrRet[0].length() == 0) {
                    StringBuilder tmpSbMsg = new StringBuilder();
                    tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
                    if (tmpBkReader != null) {
                        String tmpRetCode = tmpBkReader.getFirstText("/Transaction/TransContent/ReturnCode");
                        String tmpRetMessage = tmpBkReader.getFirstText("/Transaction/TransContent/ReturnMsg");
                        if ("0000".equals(tmpRetCode)) {
                            //总记录数
                            if (tmpAllNum == -1) {
                                tmpAllNum = Integer.parseInt(tmpBkReader.getFirstText("/Transaction/TransContent/TotalNum"));
                            }
                            if (tmpAllNum <= 0) {
                                tmpRespCode = "-1";
                                WriteBankLogLn("查无回单");
                                break;
                            }else{
                            	//执行读取具体明细节点
                            	//if else套嵌太深，把大段代码逻辑提取到外层
                            	doRead = true;
                            }
                        } else {
                            tmpRespCode = "-1";
                            WriteBankLogLn(tmpRetMessage);
                            break;
                        }
                    } else {
                        tmpRespCode = "-1";
                        WriteBankLogLn(tmpSbMsg);
                        break;
                    }
                } else {
                    tmpRespCode = "-1";
                    WriteBankLogLn(tmpStrRet[1]);
                    break;
                }
                if(doRead){
                	while (tmpBkReader.read("/Transaction/TransContent/BatchRespList/RespData")) {
                        tmpPageRdNum++;
                        tmpReadedNum++;
                        
                        ReceiptData eachData = new ReceiptData();
                        eachData.receiptNo = tmpBkReader.readedXElement.getSingleTextNotNull("BillNumber");
                        eachData.istNbr = eachData.receiptNo;
                        eachData.ownAct = pReqReceipt.actNum;
                        eachData.setBusDate(pOneDay);
                        //eachData.localFile = StringHelper.getRelativePath(destFile.getAbsolutePath(), pConfig.localSaveMainDir);
                    	//eachData.srcFile = eachFile.getName();
                        eachData.busRef = eachData.receiptNo;
                        eachData.bank = "303";//光大303
                        eachData.srcSys = "CEB01";
                        String busDate = tmpBkReader.readedXElement.getSingleTextNotNull("WriteDate");
                        if(!String.valueOf(eachData.busDate).equals(busDate)){
                        	WriteBankLogLn("日期"+busDate+"不符合预期"+String.valueOf(eachData.busDate)+"，回单编号BillNumber:" + eachData.receiptNo);
                        }
                        
                        eachData.downState = "1";
                        String acNo = tmpBkReader.readedXElement.getSingleTextNotNull("AcNo");
                        String acNo2 = tmpBkReader.readedXElement.getSingleTextNotNull("AcNo2");
                        if (!pReqReceipt.actNum.equals(acNo) && !pReqReceipt.actNum.equals(acNo2)) {
                        	WriteBankLogLn("AcNo:"+acNo+",AcNo2:"+acNo2+"均与请求账号"+pReqReceipt.actNum+"不符,回单编号BillNumber:" + eachData.receiptNo);
                        }
                        if (pReqReceipt.actNum.equals(acNo)) {
                        	eachData.moneyWay = "1";
                        	eachData.oppActNum = tmpBkReader.readedXElement.getSingleTextNotNull("AcNo2");
                        	eachData.oppActName = tmpBkReader.readedXElement.getSingleTextNotNull("AcName2");
                        	eachData.summary = tmpBkReader.readedXElement.getSingleTextNotNull("AcBankName2");
                        } else {
                        	eachData.moneyWay = "2";
                        	eachData.oppActNum = tmpBkReader.readedXElement.getSingleTextNotNull("AcNo");
                        	eachData.oppActName = tmpBkReader.readedXElement.getSingleTextNotNull("AcName");
                        	eachData.summary = tmpBkReader.readedXElement.getSingleTextNotNull("AcBankName");
                        }
                        eachData.purpose = tmpBkReader.readedXElement.getSingleTextNotNull("purpose");
                        eachData.amount = new BigDecimal(tmpBkReader.readedXElement.getSingleTextNotNull("Amount"));
                        eachData.bnkSeqNo = tmpBkReader.readedXElement.getSingleTextNotNull("FlowNumber");
                        eachData.busRef = tmpBkReader.readedXElement.getSingleTextNotNull("ClientPatchID");
                        eachData.chkCode = tmpBkReader.readedXElement.getSingleTextNotNull("ValidateCode");
                        eachData.voucherNo = tmpBkReader.readedXElement.getSingleTextNotNull("BillQueryCode");
                        eachData.cur = strCurrency;
                        
                        int inRe = receiptHelper.insertIfNotExist(eachData, true);
                        if(inRe>0){
                        	insertNum++;
                        }else if(inRe == 0){
                        	existNum++;
                        }
                        WriteBankLogLn(eachData.receiptNo+"写入数据库，影响行数："+inRe);
                    }
                }
                if (tmpPageRdNum == 0 || tmpReadedNum >= tmpAllNum) {
                    break;
                }
            }while(tmpRespCode.length() == 0 && tmpReadedNum<tmpAllNum);//分页查询
        	
        	String aLog = pReqReceipt.actNum+"，"+qryDay8+"回单数据查询完成，总数："+tmpAllNum+"，查回："+tmpReadedNum+"，已存在："+existNum+"，新增："+insertNum;
            WriteBankLogLn(aLog);
            ArrayList<String> listData = receiptHelper.getIstNbrList(pReqReceipt.actNum, pOneDay);
            aLog = pReqReceipt.actNum+"，"+qryDay8+"需要进行下载的回单文件个数："+listData.size();
            WriteBankLogLn(aLog);
            if(listData.size() <= 0){
                return null;
            }
            int succNum = 0;
            int failNum = 0;
            int zeroNum = 0;
            for(int i=0;i<listData.size();i++){
            	String istNbr = listData.get(i);
        		aLog = pReqReceipt.actNum+"，"+qryDay8+"下载"+istNbr;
                WriteBankLogLn(aLog);
                try{
                	int downRe = downEachFile(pConfig, receiptHelper, pReqReceipt.actNum, istNbr);
                	if(downRe>0){
                		succNum++;
                	}else if(downRe==0){
                		zeroNum++;
                	}else{
                		failNum++;
                	}
                }catch(Exception ex){
                	this.WriteBankLogLn(ex);
                }
            }
            aLog = pReqReceipt.actNum+"，"+qryDay8+"回单文件下载执行结束，下载成功："+succNum+"，失败："+failNum;
            if(zeroNum>0){
            	aLog+="，执行中发现有"+zeroNum+"个被其它线程下载";
            }
            WriteBankLogLn(aLog);
            if(succNum>0){
            	SyncReceipt.resetDelayCounter();
            }
        }catch(Exception ex){
        	this.WriteBankLogLn(ex);
        }finally{
        	if(receiptHelper != null){
        		receiptHelper.close();
        	}
        }
		return null;
	}
	
	private Date lastSendTime;//上次发送时间
	private long waitMil = -1;//等待的毫秒数
	
	/**根据BillNumber回单号下载文件，返回0表示之前已下载，1表示成功，-1表示失败
	 * @throws Exception */
	private int downEachFile(ReceiptProConfig pProConfig, ReceiptDataHelper pReceiptHelper, String pActNum, String pIstNbr) throws Exception{
		XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        //写入通用的头部节点
        CEB01Header bankHeader = new CEB01Header();
        bankHeader.TransCode = "b2e005023";
        bankHeader.batchID = getBatchID();
        bankHeader.JnlDateTime = new Date();
        writeCommonHeader_2(xmlWriter, bankHeader);
        xmlWriter.writeStartElement("TransContent");
        xmlWriter.writeStartElement("ReqData");
        xmlWriter.writeElementString("ClientPatchID", bankHeader.batchID);
        xmlWriter.writeElementString("OperationType", "1");//1-下载(文件生成)
        xmlWriter.writeElementString("ActNo", pActNum);
        xmlWriter.writeElementString("BillNumber", pIstNbr);
        xmlWriter.writeElementString("BeginDate", "");
        xmlWriter.writeElementString("EndDate", "");
        xmlWriter.writeElementString("BeginAmount", "");
        xmlWriter.writeElementString("EndAmount", "");
        xmlWriter.writeElementString("BeginNum", "1");
        xmlWriter.writeElementString("QueryNum", "10");
        xmlWriter.writeEndDocument();
        //生成回单
        //下载时控制频率每5秒1次
        if(lastSendTime != null){
        	if(waitMil == -1){
        		String waitSecsSet = getBankConfig().getValueAsString("waitSecsEachReqForReceipt");
                if (StringHelper.hasAnyChar(waitSecsSet)) {
                	waitMil = Long.parseLong(waitSecsSet) * 1000;
                }
                if(waitMil<0){
                	waitMil = 5000;
            	}
                WriteBankLogLn("下载间隔毫秒数："+waitMil);
        	}
        	long actualWaitMil = waitMil - DateHelper.getDifferMilSecs(new Date(), lastSendTime);
        	if(actualWaitMil>0){
        		WriteBankLogLn("需等待"+actualWaitMil+"毫秒：");
        		Thread.sleep(actualWaitMil);
        	}
        }
        String[] tmpStrRet = sendToBank_2(xmlWriter.toXmlString(), bankHeader.TransCode);
        lastSendTime = new Date();//时间频率计算保守一点，从上次接收后算起而不用发送时间
        XmlTextReader tmpBkReader;
        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                while (tmpBkReader.read("/Transaction/TransContent/RespData")) {
                	boolean doSave = false;//打标记
                    String fileName = tmpBkReader.readedXElement.getSingleTextNotNull("fileName");
                    if (!StringHelper.isNullOrEmpty(fileName)) {
                        //下载回单
                        String[] tmpStrRetDownLoad = sendToBankDownloadFile("", bankHeader.TransCode, fileName);
                        XmlTextReader tmpBkReaderDownLoad;
                        if (tmpStrRet[0].length() == 0) {
                            StringBuilder tmpSbMsgDownLoad = new StringBuilder();
                            tmpBkReaderDownLoad = loadBankRespXmlReader(tmpStrRetDownLoad[1], tmpSbMsgDownLoad);
                            if (tmpBkReaderDownLoad != null) {
                                String success = tmpBkReaderDownLoad.getFirstText("/transaction/success");
                                String error = tmpBkReaderDownLoad.getFirstText("/transaction/error");
                                if (!StringHelper.isNullOrEmpty(success) && StringHelper.isNullOrEmpty(error)) {
                                	doSave = true;//把主逻辑提取到if else之外
                                } else {
                                    WriteBankLogLn(pIstNbr + "回单文件下载失败：" + error);
                                }
                            }else{
                            	WriteBankLogLn(pIstNbr + "加载响应xml失败："+tmpSbMsgDownLoad.toString());
                            }
                        } else {
                            WriteBankLogLn(pIstNbr + "回单文件下载失败：" + tmpStrRet[1]);
                        }
                    } else {
                        WriteBankLogLn(pIstNbr + "回单文件生成失败：" + tmpStrRet[1]);
                    }
                    
                    //执行保存
                    if(doSave){
                    	//从指定的银行前置回单目录取
                    	String bkFilePath = StringHelper.trimEndFileSp(bankFront.bankReceiptMainDir)+File.separator+fileName;
                    	File receiptFile = new File(bkFilePath);
                    	if(receiptFile.exists()){
                    		ReceiptData aData = pReceiptHelper.loadFromDbByIstNbr(pActNum, pIstNbr);
                            if(aData != null){
                            	if("2".equals(aData.downState)){
                            		WriteBankLogLn(pIstNbr + "回单文件已下载");
                            		receiptFile.delete();
                            		return 0;
                                }
                            	try{
                                	//按月建目录存下载的压缩文件
                            		String saveDirPath = pProConfig.getSaveSubDir(reqHeader, aData.getBusDate()) + File.separator + aData.busDate + File.separator + pActNum;
                                    String saveFilePath = saveDirPath+File.separator+fileName;
                                    aData.downState="3";//先置为失败
                                    
                                    aData.downTime=new Date();
                            		aData.srcFile = fileName;
                            		aData.localFile = pProConfig.getPathRelativeToMain(saveFilePath);
                            		
                            		File destFile = new File(saveFilePath);
                            		if(destFile.exists() && destFile.length() != receiptFile.length()){
                            			destFile.delete();
                            		}
                            		destFile = new File(saveFilePath);
                            		if(!destFile.exists()){
                            			FileHelper.copyFile(receiptFile, destFile);
                            			aData.downInfo="复制成功";
                            		}else{
                            			aData.downInfo="文件之前已保存成功";
                            		}
                            		if(destFile.exists()){
                            			aData.downState="2";
                            		}else{
                            			aData.downInfo="复制失败";
                            		}
                                }catch(Exception ex){
                                	WriteBankLogLn(ex, pIstNbr+"复制文件"+fileName);
                                	aData.downInfo = LogHelper.getStackTrace(ex);
                                }
                                int rowsAff = pReceiptHelper.updateDownState(aData);
                    			if(rowsAff > 0){
                    				if("2".equals(aData.downState)){
                    					receiptFile.delete();
                                		return 1;
                    				}else{
                    					receiptFile.delete();
                                		return -1;
                    				}
                    			}else{
                    				WriteBankLogLn(pIstNbr+"，文件名为" + fileName + "，更新downState为"+aData.downState+"，影响行数："+rowsAff);
                    			}
                            }else{
                            	WriteBankLogLn(pIstNbr + "找不到回单数据");
                            }
                    	}else{
                    		WriteBankLogLn(pIstNbr + "对应的文件不存在，请确认BankFront中的bankReceiptMainDir配置，文件路径："+bkFilePath);
                    	}
                    }
                }//while循环
            } else {
                WriteBankLogLn(pIstNbr + "回单文件生成失败：" + tmpSbMsg.toString());
            }
        } else {
            WriteBankLogLn(pIstNbr + "回单文件生成失败：" + tmpStrRet[1]);
        }
        return -1;
	}
}
